package com.light.gamecomponents.physics;

import javax.microedition.khronos.opengles.GL10;

import org.anddev.andengine.audio.sound.Sound;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.entity.particle.ParticleSystem;
import org.anddev.andengine.entity.particle.emitter.CircleOutlineParticleEmitter;
import org.anddev.andengine.entity.particle.initializer.AlphaInitializer;
import org.anddev.andengine.entity.particle.initializer.ColorInitializer;
import org.anddev.andengine.entity.particle.modifier.AlphaModifier;
import org.anddev.andengine.entity.particle.modifier.ColorModifier;
import org.anddev.andengine.entity.particle.modifier.ExpireModifier;
import org.anddev.andengine.entity.particle.modifier.ScaleModifier;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.light.gamecomponents.gravitylight.GravityLight;
import com.light.roller.ResourceManager;
import com.light.roller.Roller;

public class PhysicsBox extends PhysicsComponents implements ContactListener{
	
	private Sound m_collideSound;
	
	public PhysicsBox(Roller game, String resourceName, Vector2 initialPosition, Vector2 size) 
	{
		super(game, resourceName, initialPosition, size);
	}

	@Override
	public void onUpdate(float pSecondsElapsed) {

	}

	@Override
	public void reset() {
		
	}

	@Override
	public void onLoadResources() {
		ResourceManager.onLoadResources(m_resourceName, m_game);
		m_textureRegion = ResourceManager.getTextureRegion(m_resourceName);
		ResourceManager.onLoadSoundResources("Box_Crack", m_game);
		m_collideSound = ResourceManager.getSound("Box_Crack");	
		particleEffectLoadR();
	}
	
	@Override
	public void unLoadResources() {
		m_textureRegion = null;
		ResourceManager.unLoadResources(m_resourceName, m_game);
	}
	
	
	@Override
	public void onLoadScene(Scene scene, PhysicsWorld physicsWorld) {
		FixtureDef objectFixtureDef = PhysicsFactory.createFixtureDef(BOX_EIGEN, 0.0f, 1.0f);
		
		objectFixtureDef.filter.categoryBits = Roller.CATEGORYBIT_NORMAL;
		objectFixtureDef.filter.maskBits = Roller.MASKBIT_NORMAL;
		
		m_sprite = new Sprite(m_initialPosition.x, 
				  		      m_initialPosition.y,
                              m_textureRegion);
		
		
		m_body = PhysicsFactory.createBoxBody(physicsWorld, 
											  m_sprite, 
											  BodyType.DynamicBody, 
											  objectFixtureDef);
		
		
		particleEffectLoadS(scene);	
		scene.attachChild(m_sprite);
		
		m_physicsConnector = new PhysicsConnector(m_sprite, m_body, true, true);
		physicsWorld.registerPhysicsConnector(m_physicsConnector);
		((RollerPhysicsWorld)physicsWorld).registerContactListener(this);
		
		m_body.setType(BodyType.StaticBody);
		m_body.setLinearVelocity(new Vector2(0.0f, 0.0f));
		m_body.setAngularVelocity(0);
		getSprite().setColor(0.5f, 0.5f, 0.5f);
		
		
		
	}
	
	private void particleEffectLoadR()
	{
		ResourceManager.onLoadResources("particle_point",m_game);
	}
	
	
	private CircleOutlineParticleEmitter particleEmitter;
	private ParticleSystem particleSystem ;
	static float ParticleSystemRadius = 30;
	
	private void particleEffectLoadS(Scene scene)
	{
		ParticleSystemRadius = m_sprite.getWidth()/3;
		particleEmitter = new CircleOutlineParticleEmitter(0, 0, ParticleSystemRadius);
		particleSystem = new ParticleSystem(particleEmitter, 10, 10, 20,ResourceManager.getTextureRegion("particle_point"));
		
		particleSystem.addParticleInitializer(new ColorInitializer(1, 1, 1));
		particleSystem.addParticleInitializer(new AlphaInitializer(1));
		particleSystem.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
		particleSystem.addParticleModifier(new ScaleModifier(1.0f, 2.0f, 0, 2));
		particleSystem.addParticleModifier(new ColorModifier(1, 0, 1, 0, 1, 0, 0, 2));
		particleSystem.addParticleModifier(new AlphaModifier(1, 0, 0, 2));
		particleSystem.addParticleModifier(new ExpireModifier(2f, 2f));

		scene.attachChild(particleSystem);
		
		scene.registerUpdateHandler(new IUpdateHandler(){

			@Override
			public void onUpdate(float pSecondsElapsed) {
				particleEmitter.setCenter(m_sprite.getX()+m_sprite.getWidth()/2-16,m_sprite.getY()+m_sprite.getHeight()/2-16);
			}

			@Override
			public void reset() {
				// TODO Auto-generated method stub
				
			}});
	}
	
	public void stopBody() 
	{ 
		super.stopBody();
		particleSystem.setIgnoreUpdate(true);
	}
	public void startBody() 
	{ 
		super.startBody();
		particleSystem.setIgnoreUpdate(false);
	}
	
	
	@Override
	public void removeFromScene(Scene scene, PhysicsWorld physicsWorld) 
	{
		physicsWorld.unregisterPhysicsConnector(m_physicsConnector);
		scene.detachChild(m_sprite);
		physicsWorld.destroyBody(m_body);		
	
	}

	@Override
	public void onLoadEngine() {
		
	}

	@Override
	public void setPosition(int x, int y) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void beginContact(Contact contact) {
		if (contact.getFixtureA().getBody() == this.m_body || 
			contact.getFixtureB().getBody() == this.m_body)
			
		{
			Vector2 vecNormal = contact.GetWorldManifold().getNormal();
		    Vector2 vecImpulse = new Vector2(vecNormal.x * m_body.getLinearVelocity().x, 
		    		                         vecNormal.y * m_body.getLinearVelocity().y); 
			
			float v = vecImpulse.x * vecImpulse.x + 
					  vecImpulse.y * vecImpulse.y;
			
			if (v >= 25)
			{
				if (Roller.playMusic)
					m_collideSound.play();
			}
		}
	}

	@Override
	public void endContact(Contact contact) {
		// TODO Auto-generated method stub
	}

	@Override
	public void rotate(float angle) {
		// TODO Auto-generated method stub
		
	}	
	
	@Override
	public boolean isInLight(GravityLight light)
	{
		Vector2 disVec = new Vector2(getSpritePosition().x - light.getSpritePosition().x, 
				 					 getSpritePosition().y - light.getSpritePosition().y);

		float dis = (float)Math.sqrt(disVec.x * disVec.x + disVec.y * disVec.y);
		float minDis = m_sprite.getWidth() / 2 + light.getWidth() / 2 - 15;
		
		if (dis <= minDis)
			return true;
		else
			return false;
		
	}
}
